const neo4j = require('neo4j-driver');

class Neo4jService {
  constructor() {
    this.driver = null;
    this.session = null;
    this.currentSettings = {
      url: process.env.NEO4J_URI,
      username: process.env.NEO4J_USERNAME,
      password: process.env.NEO4J_PASSWORD,
      database: 'neo4j'
    };
    this.init();
  }

  init() {
    try {
      this.driver = neo4j.driver(
        this.currentSettings.url,
        neo4j.auth.basic(this.currentSettings.username, this.currentSettings.password)
      );
      console.log('Neo4j驱动初始化成功');
    } catch (error) {
      console.error('Neo4j驱动初始化失败:', error);
    }
  }

  // 更新连接配置
  async updateConnection(url, username, password, database = 'neo4j') {
    try {
      // 关闭现有连接
      if (this.driver) {
        await this.driver.close();
      }
      
      // 更新设置
      this.currentSettings = {
        url,
        username,
        password,
        database
      };
      
      // 创建新的驱动
      this.driver = neo4j.driver(
        url,
        neo4j.auth.basic(username, password)
      );
      
      console.log('Neo4j连接配置已更新');
      return true;
    } catch (error) {
      console.error('更新Neo4j连接失败:', error);
      throw error;
    }
  }
  
  // 获取当前设置
  getCurrentSettings() {
    return {
      url: this.currentSettings.url,
      username: this.currentSettings.username,
      database: this.currentSettings.database,
      // 不返回密码
      hasPassword: !!this.currentSettings.password
    };
  }

  getSession() {
    if (!this.driver) {
      throw new Error('Neo4j驱动未初始化');
    }
    return this.driver.session({
      database: this.currentSettings.database
    });
  }

  async testConnection() {
    const session = this.getSession();
    try {
      await session.run('RETURN 1');
      return true;
    } catch (error) {
      console.error('Neo4j连接测试失败:', error);
      return false;
    } finally {
      await session.close();
    }
  }

  async runQuery(query, parameters = {}) {
    const session = this.getSession();
    try {
      const result = await session.run(query, parameters);
      return result.records.map(record => {
        const obj = {};
        record.keys.forEach(key => {
          const value = record.get(key);
          if (neo4j.isNode(value)) {
            obj[key] = {
              id: value.identity.toNumber(),
              labels: value.labels,
              properties: value.properties
            };
          } else if (neo4j.isRelationship(value)) {
            obj[key] = {
              id: value.identity.toNumber(),
              type: value.type,
              properties: value.properties,
              startNodeId: value.start.toNumber(),
              endNodeId: value.end.toNumber()
            };
          } else if (neo4j.isPath(value)) {
            obj[key] = {
              start: value.start,
              end: value.end,
              segments: value.segments,
              length: value.length
            };
          } else {
            obj[key] = value;
          }
        });
        return obj;
      });
    } catch (error) {
      console.error('查询执行失败:', error);
      throw error;
    } finally {
      await session.close();
    }
  }

  // 创建节点
  async createNode(label, properties) {
    const query = `CREATE (n:${label} $properties) RETURN n`;
    return await this.runQuery(query, { properties });
  }

  // 创建关系
  async createRelationship(fromNodeId, toNodeId, relationshipType, properties = {}) {
    const query = `
      MATCH (a), (b)
      WHERE id(a) = $fromNodeId AND id(b) = $toNodeId
      CREATE (a)-[r:${relationshipType} $properties]->(b)
      RETURN r
    `;
    return await this.runQuery(query, { fromNodeId, toNodeId, properties });
  }

  // 获取所有节点
  async getAllNodes() {
    const query = 'MATCH (n) RETURN n LIMIT 100';
    return await this.runQuery(query);
  }

  // 获取所有关系
  async getAllRelationships() {
    const query = 'MATCH (a)-[r]->(b) RETURN a, r, b LIMIT 100';
    return await this.runQuery(query);
  }

  // 获取图谱数据（节点和关系）
  async getGraphData() {
    const query = `
      MATCH (n)-[r]->(m)
      RETURN n, r, m
      LIMIT 50
    `;
    const result = await this.runQuery(query);
    
    const nodes = new Map();
    const relationships = [];
    
    result.forEach(record => {
      // 添加起始节点
      if (record.n && !nodes.has(record.n.id)) {
        nodes.set(record.n.id, {
          id: record.n.id,
          label: record.n.labels[0] || 'Node',
          properties: record.n.properties
        });
      }
      
      // 添加结束节点
      if (record.m && !nodes.has(record.m.id)) {
        nodes.set(record.m.id, {
          id: record.m.id,
          label: record.m.labels[0] || 'Node',
          properties: record.m.properties
        });
      }
      
      // 添加关系
      if (record.r) {
        relationships.push({
          id: record.r.id,
          source: record.r.startNodeId,
          target: record.r.endNodeId,
          type: record.r.type,
          properties: record.r.properties
        });
      }
    });
    
    return {
      nodes: Array.from(nodes.values()),
      relationships
    };
  }

  // 搜索节点
  async searchNodes(searchTerm) {
    const query = `
      MATCH (n)
      WHERE any(prop in keys(n) WHERE toString(n[prop]) CONTAINS $searchTerm)
      RETURN n
      LIMIT 20
    `;
    return await this.runQuery(query, { searchTerm });
  }

  // 删除节点
  async deleteNode(nodeId) {
    const query = `
      MATCH (n)
      WHERE id(n) = $nodeId
      DETACH DELETE n
    `;
    return await this.runQuery(query, { nodeId });
  }

  // 初始化示例数据
  async initSampleData() {
    try {
      // 清空现有数据
      await this.runQuery('MATCH (n) DETACH DELETE n');
      
      // 创建示例节点
      const persons = [
        { name: '张三', age: 30, occupation: '软件工程师' },
        { name: '李四', age: 28, occupation: '产品经理' },
        { name: '王五', age: 35, occupation: '设计师' }
      ];
      
      const companies = [
        { name: '科技公司A', industry: '互联网', founded: 2010 },
        { name: '创新公司B', industry: '人工智能', founded: 2015 }
      ];
      
      // 创建人员节点
      for (const person of persons) {
        await this.createNode('Person', person);
      }
      
      // 创建公司节点
      for (const company of companies) {
        await this.createNode('Company', company);
      }
      
      // 创建关系
      await this.runQuery(`
        MATCH (p:Person {name: '张三'}), (c:Company {name: '科技公司A'})
        CREATE (p)-[:WORKS_FOR {position: '高级工程师', since: 2020}]->(c)
      `);
      
      await this.runQuery(`
        MATCH (p:Person {name: '李四'}), (c:Company {name: '科技公司A'})
        CREATE (p)-[:WORKS_FOR {position: '产品经理', since: 2019}]->(c)
      `);
      
      await this.runQuery(`
        MATCH (p:Person {name: '王五'}), (c:Company {name: '创新公司B'})
        CREATE (p)-[:WORKS_FOR {position: '首席设计师', since: 2021}]->(c)
      `);
      
      await this.runQuery(`
        MATCH (p1:Person {name: '张三'}), (p2:Person {name: '李四'})
        CREATE (p1)-[:KNOWS {relationship: '同事', since: 2020}]->(p2)
      `);
      
      console.log('示例数据初始化完成');
    } catch (error) {
      console.error('初始化示例数据失败:', error);
      throw error;
    }
  }

  async close() {
    if (this.driver) {
      await this.driver.close();
      console.log('Neo4j连接已关闭');
    }
  }
}

module.exports = new Neo4jService();